package com.vinjogames.gfx;

import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

import android.graphics.Bitmap;
import android.graphics.PointF;
import android.opengl.GLUtils;

import com.vinjogames.util.VertexBuffer;


public class Font {
	private static final int WIDTH  = 32;	
	private static final int HEIGHT = 32;
	private static final int ROWS   = 16;
	private static final int COLS   = 16;
	
	private static final float mOffset = 0.4f; 
	
	private static int[] mTextures;
	private static Bitmap mAllChars;
	private static FloatBuffer mVertexBuffer;
	private static FloatBuffer mTextureBuffer;
	
	// For use with block text
	private static char[] stringArray;
	private static int index;

	public static void load(GL10 gl){
		mTextures = new int[127];
		
		mAllChars = SpriteSheet.getInstance().getFontBitmap();
		for(int i = 0; i < mTextures.length; i++){
			mTextures[i] = getTexture(gl, i);
		}
		mAllChars.recycle();

		mVertexBuffer = VertexBuffer.getVertexBuffer(new float[]{
				-.5f,-.5f, 0, // V2
				-.5f, .5f, 0, // V1
				.5f,-.5f, 0, // V3
				.5f, .5f, 0  // V4
		});
		mTextureBuffer = VertexBuffer.getVertexBuffer(new float[]{
				0.0f, 1.0f,
				0.0f, 0.0f,
				1.0f, 1.0f,
				1.0f, 0.0f
		});
	}
	
	private static int getTexture(GL10 gl, int c){
		int[] texture = new int[1];
		gl.glGenTextures(1, texture, 0);
		Bitmap bitmap = Bitmap.createBitmap(mAllChars, c%COLS * WIDTH, c/ROWS * HEIGHT, WIDTH, HEIGHT);
		gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
		bitmap.recycle();
		return texture[0];
	}
	
	public static void drawStringBlockLeftAligned(GL10 gl, String text, PointF location, float glWidth, float scale){
		if(text.length() * (1 - mOffset) * scale > glWidth){
			index = (int)(glWidth / (1 - mOffset) / scale) - 1;
			while(true){
				stringArray = text.toCharArray();
				while(stringArray[index] != ' ')
					--index;
				drawStringLeftAligned(gl, text.substring(0, index), location, scale);
				text = text.substring(index, text.length());
				location.set(location.x - index * (1-mOffset) * scale * 0.5f, location.y - (1-mOffset) * scale);
				if((int)(glWidth / (1 - mOffset) / scale) > text.length())
					break;
				else index = (int)(glWidth / (1 - mOffset) / scale) - 1;
			}
		}
		drawStringLeftAligned(gl, text, location, scale);
	}
	
	public static void drawStringLeftAligned(GL10 gl, String text, PointF location, float scale){
		location.set(location.x + text.length() * (1-mOffset) * scale * 0.5f, location.y);
		drawString(gl, text, location, scale);
	}

	public static void drawString(GL10 gl, String text, PointF location, float scale){
		if(mTextures == null){ load(gl); }

		gl.glPushMatrix();
		gl.glLoadIdentity();
		
		gl.glScalef(scale, scale, 1);
		gl.glTranslatef((location.x-(Camera.GL_WIDTH/2))/scale - (text.length()-1)*(1f-mOffset)/2, 
				        (location.y-(Camera.GL_HEIGHT/2))/scale, Camera.Z_DISTANCE);	
		gl.glColor4f(1f, 1f, 1f, 1f); 
		 
		// Point to Buffers
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		// Set Face
		gl.glFrontFace(GL10.GL_CW);
		// Point to buffer
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);
		
		for(int i = 0; i < text.length(); i++){
			gl.glTranslatef(i==0?0:(1f-mOffset), 0, 0);	
			gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[text.charAt(i)]);
			gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);//Always 4 because its a square
		}
		
		// Disable Client State before Leaving
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		
		gl.glPopMatrix();
	}
	
	public static void drawString(GL10 gl, String text, float scale){
		if(mTextures == null){ load(gl); }

		gl.glPushMatrix();
		
		gl.glScalef(scale, scale, 1);	
		gl.glColor4f(1f, 1f, 1f, 1f); 
		 
		// Point to Buffers
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		// Set Face
		gl.glFrontFace(GL10.GL_CW);
		// Point to buffer
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);
		
		for(int i = 0; i < text.length(); i++){
			gl.glTranslatef(i==0?0:(1f-mOffset), 0, 0);	
			gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[text.charAt(i)]);
			gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);//Always 4 because its a square
		}
		
		// Disable Client State before Leaving
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		
		gl.glPopMatrix();
	}
}
